<!-- prettier-ignore -->
<template>
  <div class="cesium-map">
    <div id="cesiumContainer"></div>
    <div class="bottom-map-switch">
      <!--切换底图-->
      <el-select v-model="currentBaseMap" placeholder="请选择" style="width: 100px">
        <el-option v-for="(item,index) in baseMaps" :key="index" :label="item.name" :value="item.name">
        </el-option>
      </el-select>
    </div>
    <div v-if="bottomData" class="bottom-control">
      <span>帧率: {{ bottomData.fps }}</span>
      <span>网络延迟: {{ bottomData.netDelay }}</span>
      <span>经度: {{ bottomData.lng }}°</span>
      <span>纬度: {{ bottomData.lat }}°</span>
      <span>高度: {{ bottomData.height }}米</span>
      <span>偏航角: {{ bottomData.heading }}°</span>
      <span>俯仰角: {{ bottomData.pitch }}°</span>
      <span>翻滚角: {{ bottomData.roll }}°</span>
    </div>
  </div>
</template>

<script>
import {addskyLayer, addLayer} from "@/utils/map.js";

export default {
  data() {
    return {
      bottomData: null,
      terrainShow: false,
      tdtToken: "1fd463af45319bc45b394dac4a87006b",
      currentBaseMap: "默认",
      baseMaps: [],
    };
  },

  watch: {
    currentBaseMap(val) {
      const {url} = this.baseMaps.find(item => item.name === val)
      this.viewer.imageryLayers.remove(this.Global.defaultImageLayer)
      this.Global.defaultImageLayer = null
      this.Global.defaultImageLayer = addskyLayer(this.viewer, url);
    }
  },

  methods: {
    dropdownClick(val) {
      this.currentBaseMap = val.name;
    },
    // 初始化地图
    createdMap() {
      var cesiumTerrainProvider = new Cesium.CesiumTerrainProvider({
        url: window.serviceUrl.terrainUrl,
        requestVertexNormals: true,
        requestWaterMask: true,
      });
      this.viewer = new Cesium.Viewer("cesiumContainer", {
        terrainProvider: this.terrainShow ? cesiumTerrainProvider : null,
        // terrainProvider: cesiumTerrainProvider,
        contextOptions: {
          webgl: {
            alpha: true,
            depth: true,
            stencil: true,
            antialias: true,
          },
        },
        useBrowserRecommendedResolution: true,
        selectionIndicator: false,
        homeButton: false,
        animation: false, //是否显示动画控件
        baseLayerPicker: false, //是否显示图层选择控件
        geocoder: false, //是否显示地名查找控件
        timeline: false, //是否显示时间线控件
        sceneModePicker: false, //是否显示投影方式控件
        navigationHelpButton: false, //是否显示帮助信息控件
        infoBox: false, //是否显示点击要素之后显示的信息
        imageryProvider: false,
        fullscreenButton: false,
        shouldAnimate: true,
        requestRenderMode: true,
      });
      // this.viewer.scene.globe.depthTestAgainstTerrain = true;
      this.viewer.scene.primitives.destroyPrimitives = false;
      this.viewer.scene.postProcessStages._fxaa.enabled = true;
      this.viewer.scene.screenSpaceCameraController.enableCollisionDetection = true;
      this.viewer._cesiumWidget._creditContainer.style.display = "none";
      this.viewer.screenSpaceEventHandler.removeInputAction(
          Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
      );

      //指北针
      let options = {};
      // 用于在使用重置导航重置地图视图时设置默认视图控制。接受的值是Cesium.Cartographic 和 Cesium.Rectangle.
      options.defaultResetView = Cesium.Rectangle.fromDegrees(80, 22, 130, 50);
      // 用于启用或禁用罗盘。true是启用罗盘，false是禁用罗盘。默认值为true。如果将选项设置为false，则罗盘将不会添加到地图中。
      options.enableCompass = true;
      // 用于启用或禁用缩放控件。true是启用，false是禁用。默认值为true。如果将选项设置为false，则缩放控件将不会添加到地图中。
      options.enableZoomControls = false;
      // 用于启用或禁用距离图例。true是启用，false是禁用。默认值为true。如果将选项设置为false，距离图例将不会添加到地图中。
      options.enableDistanceLegend = false;
      // 用于启用或禁用指南针外环。true是启用，false是禁用。默认值为true。如果将选项设置为false，则该环将可见但无效。
      options.enableCompassOuterRing = true;
      CesiumNavigation.umd(this.viewer, options);

      this.Global.viewer = this.viewer;
      this.$emit("mapIsLoad", true);
    },

    cameraChange() {
      let fps, netDelay, lng, lat, height, heading, pitch, roll;
      this.viewer.scene.debugShowFramesPerSecond = true;
      if (this.viewer.scene._performanceDisplay) {
        fps = this.viewer.scene._performanceDisplay._fpsText.data;
        netDelay = this.viewer.scene._performanceDisplay._msText.data;
      }
      lng = Cesium.Math.toDegrees(
          this.viewer.camera.positionCartographic.longitude
      ).toFixed(6);
      lat = Cesium.Math.toDegrees(
          this.viewer.camera.positionCartographic.latitude
      ).toFixed(6);
      height = this.viewer.camera.positionCartographic.height.toFixed(2);
      heading = Cesium.Math.toDegrees(
          Number(this.viewer.camera.heading)
      ).toFixed(6);
      pitch = Cesium.Math.toDegrees(Number(this.viewer.camera.pitch)).toFixed(
          6
      );
      roll = Cesium.Math.toDegrees(Number(this.viewer.camera.roll)).toFixed(6);
      this.bottomData = Object.assign(this.bottomData ? this.bottomData : {}, {
        fps,
        netDelay,
        lng,
        lat,
        height,
        heading,
        pitch,
        roll,
      });
    },
    // 获取底部控件参数
    getControlParams() {
      try {
        setTimeout(() => {
          this.clickMap();
          this.viewer.scene.camera.percentageChanged = 0.05;
          this.viewer.camera.changed.addEventListener(
              this.throttleCameraChange,
              2000
          );
        }, 2000);
      } catch (error) {
        console.log("获取底部控件参数方法报错：", error);
      }
    },
    // 鼠标移动获取坐标
    getCoordinate(e) {
      let cartesian = null;
      let primitive = this.viewer.scene.pick(e.startPosition);
      if (primitive) {
        cartesian = this.viewer.scene.pickPosition(e.startPosition);
      } else {
        let ray = this.viewer.camera.getPickRay(e.startPosition);
        cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
      }
      if (!cartesian) return;
      const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
      const lng = Cesium.Math.toDegrees(cartographic.longitude).toFixed(6);
      const lat = Cesium.Math.toDegrees(cartographic.latitude).toFixed(6);
      this.bottomData = Object.assign(this.bottomData ? this.bottomData : {}, {
        lng,
        lat,
      });
    },

    // 左键移动事件
    clickMap() {
      !this.handler &&
      (this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.canvas));
      this.handler.setInputAction((e) => {
        // this.debouncedGetCoordinate(e)
        this.throttledGetCoordinate(e);
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    },

    // 防抖函数
    debounce(func, wait) {
      // 定义一个变量 timeout，用于存储 setTimeout 的返回值
      let timeout;
      // 返回一个函数，接收任意数量的参数
      return function (...args) {
        // 将当前上下文（即调用函数的上下文）存储在变量 context 中
        const context = this;
        // 清除上一次设置的定时器
        clearTimeout(timeout);
        // 设置一个新的定时器，等待 wait 毫秒后执行 func 函数，并将函数的上下文和参数传递给 func
        timeout = setTimeout(() => func.apply(context, args), wait);
      };
    },
    // 节流函数
    throttle(func, limit) {
      // 上一次函数执行的时间
      let lastRan;
      // 上一次的函数执行实例
      let lastFunc;
      // 返回一个新的函数
      return function () {
        // 当前函数的上下文
        const context = this;
        // 当前函数的参数
        const args = arguments;
        // 如果上一次函数没有执行过
        if (!lastRan) {
          // 直接执行函数
          func.apply(context, args);
          // 记录函数执行的时间
          lastRan = Date.now();
        } else {
          // 如果上一次函数执行过
          // 清除上一次函数执行的定时器
          clearTimeout(lastFunc);
          // 设置一个新的定时器
          lastFunc = setTimeout(function () {
            // 如果距离上一次函数执行的时间超过了限制时间
            if (Date.now() - lastRan >= limit) {
              // 执行函数
              func.apply(context, args);
              // 记录函数执行的时间
              lastRan = Date.now();
            }
          }, limit - (Date.now() - lastRan));
        }
      };
    },
  },

  created() {
    if (window.appSettings) {
      const {token} = window.appSettings.engineering.baseMap.tianditu
      if (token) {
        this.tdtToken = token;
      }
      this.terrainShow =
          window.appSettings.engineering.baseMap.other.terrainShow;
    }
    this.viewer = null;
    this.handler = null;
    this.throttledGetCoordinate = this.throttle((e) => {
      this.getCoordinate(e);
    }, 500);
    this.throttleCameraChange = this.throttle(() => {
      this.cameraChange();
    }, 500);
  },

  async mounted() {
    this.createdMap();
    let imageUrl = window.serviceUrl.skyImageUrl + `&tk=${this.tdtToken}`;
    if (process.env.NODE_ENV === 'development') {
      try {
        const data = await this.$get('local/local.json')
        imageUrl = data.imageUrl
      } catch (error) {
        imageUrl = window.serviceUrl.skyImageUrl
      }
    }
    this.Global.defaultImageLayer = addskyLayer(this.viewer, imageUrl);
    this.getControlParams();
    window.appSettings?.engineering?.baseMap?.custom.forEach((item) => {
      if (item.isCheck) {
        this.baseMaps.push(item);
      }
    });
    this.baseMaps.push({
      url: imageUrl,
      name: "默认",
    });
  },

  beforeDestroy() {
    this.handler && this.handler.destroy();
    this.handler = null;
    this.viewer.camera.changed.removeEventListener(this.cameraChange);
    this.cameraChange = null;
  },
};
</script>

<style lang="less" scoped>
.cesium-map,
#cesiumContainer {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  z-index: 10;
}

.cesium-map {
  .bottom-map-switch {
    position: absolute;
    bottom: 30px;
    right: 0;
    z-index: 11;
    border-radius: 2px;
    color: #70a0d6;
  }

  .bottom-control {
    position: fixed;
    bottom: 0;
    display: flex;
    align-items: center;
    width: 100%;
    height: 30px;
    padding: 0 30px;
    box-sizing: border-box;
    background-color: #333333;
    z-index: 11;

    span {
      margin-right: 30px;
      font-size: 10px;
      color: #e6e6e6;
    }
  }
}
</style>

<style lang="less">
.compass {
  top: 30px;
  right: 20px;

  .compass-rotation-marker,
  .compass-outer-ring {
    width: 90%;
    height: 90%;
  }

  .compass-outer-ring {
    background: url(~@/assets/image/toolBar/zhibeizhen.png) no-repeat;
    background-size: 100% 100%;
    background-size: 100%;
  }

  .compass-outer-ring-background,
  .compass-gyro-background,
  .compass-gyro {
    display: none;
  }
}

.cesium-performanceDisplay-defaultContainer {
  display: none !important;
}
</style>
